package com.lemon.ai.socket.packets.spiritgame.model.generator.utils;

import static com.lemon.ai.socket.packets.spiritgame.model.generator.utils.StringUtils.firstToUpperCase;
import static com.lemon.ai.socket.packets.spiritgame.model.generator.utils.StringUtils.generateClassName;
import static com.lemon.ai.socket.packets.spiritgame.model.generator.utils.StringUtils.generateParameterName;
import static com.lemon.ai.socket.packets.spiritgame.model.generator.utils.StringUtils.generatePropertyFromColumn;
import static com.lemon.ai.socket.packets.spiritgame.model.generator.utils.StringUtils.hump;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.lemon.ai.socket.packets.spiritgame.model.dto.Column;
import com.lemon.ai.socket.packets.spiritgame.model.dto.Property;
import com.lemon.ai.socket.packets.spiritgame.model.dto.Table;

public class StringParser {

	private static String PS = "ps.setPROPERTY_TYPE(COUNT, PROPERTY_NAME);";
	private static String RS = "CLASS_PARAMETER.setPARAMETER_NAME(rs.getPROPERTY_TYPE(\"PROPERTY_NAME\"));";

	/**
	 * 把字段的整型数据类型更新为属性的字符串型数据类型
	 * 
	 * @param type
	 *            字段数据类型
	 * @return 属性数据类型
	 */
	public static String updateTypeFromDb(int type) {

		boolean openWar = false;
		String t = "";
		switch (type) {
		case -7://bit
			t = "boolean";
			break;
		case -6:
			if(openWar)System.err.println("警告: TINYINT 转换为 short");
			t = "short";
			break;
		case -5://BIGINT
			if(openWar)System.err.println("警告: BIGINT 转换为 long");
			t = "long";
			break;
		case -3:
			t = "byte []";
			break;
		case -1:
			t = "String";
			break;
		case 1:
			//			t = "char";
			t = "byte";
			break;
		case 3://decimal
			if(openWar)System.err.println("警告: decimal 转换为 int");
			t = "int";
			break;
		case 4:
			t = "int";
			break;
		case 5:
			t = "short";
			break;
		case 6:
			t = "float";
			break;
		case 7:
			t = "float";
			break;
		case 8:
			t = "double";
			break;
		case 12:
			t = "String";
			break;
		case 16:
			t = "boolean";
			break;
		case 91:
			t = "Date";
			break;
		case 93:
			t = "Date";
			break;
		default:
			System.err.println("类型:" + type);
			break;
		}

		return t;
	}

	/**
	 * 根据该表的所有属性生成ADD_METHOD里面的COLUMN_NAMES字符串
	 * 
	 * @param cs
	 *            字段List
	 * @return COLUMN_NAMES字符串
	 */
	public static String generateColumnNames(List<Column> cs) {
		String s = cs.get(0).getName();
		for (int i = 1; i < cs.size(); i++)
			s += ", " + cs.get(i).getName();
		return s;
	}

	/**
	 * 根据表的属性数量生成ADD_METHOD里面的COLUMN_?S字符串
	 * 
	 * @param cs
	 *            字段List
	 * @return COLUMN_?S字符串
	 */
	public static String generateColumn_s(List<Column> cs) {
		String s = "?";
		for (int i = 1; i < cs.size(); i++)
			s += ", ?";
		return s;
	}

	/**
	 * add方法   insert into *** 
	 * 
	 * 				.....
	 * 
	 * 省略号部分即返回值
	 * @param table
	 * @return
	 */
	public static CharSequence generatePsSets_add(Table table) {
		List<Column> cs = table.getColumns();

		String parameterName = generateParameterName(table.getName());
		cs = new ArrayList<Column>(cs);
		String ps = "";

		Map<String, List<Column>> s = table.getSameColumns();

		Set<String> fund = new HashSet<String>();

		for (int i = 0; i < cs.size(); i++) {
			Property p = generatePropertyFromColumn(cs.get(i));
			//			private static String PS = "ps.setPROPERTY_TYPE(COUNT, PROPERTY_NAME);";
			String key = cs.get(i).getName().replaceAll("[0-9]", "");
			if(s.containsKey(key)) {

				if(!fund.contains(key)) {
					String temp = "\r\t\t\tfor(int i = 0; i < COL_SIZE; i++) {\r" +
							"\t\t\t\tCOL_SETS\r" +
							"\t\t\t}\r";
					temp = temp.replaceAll("COL_SIZE", s.get(key).size() + "");
					temp = temp.replaceAll("COL_SETS", "ps.setPROPERTY_TYPE( i + " + (i + 1) + ", " + parameterName +  ".get" +generateClassName(key) + "(i));");
					temp = temp.replaceAll("PROPERTY_TYPE", generateClassName(p.getType()));
					ps += temp;
					fund.add(key);
				}
				continue;
			}

			ps += PS;
			String prop = parameterName + ".get"
					+ generateClassName(p.getName()) + "()";
			if ("Date".equals(p.getType()))
				prop = "new java.sql.Date(" + prop + ".getTime())";

			Column c = cs.get(i);

			String tn = c.getTypename();



			if(
					!tn.equals("INTEGER") &&
					!tn.equals("VARCHAR") &&
					!tn.equals("BIGINT") &&
					!tn.equals("SMALLINT") &&
					!tn.equals("INTEGER") &&
					!tn.equals("CHAR") &&
					!tn.equals("INTEGER") &&
					!tn.equals("TINYINT") &&
					!tn.equals("DECIMAL") &&
					!tn.equals("TIMESTAMP") &&
					!tn.equals("BIT") &&
					!tn.equals("FLOAT") &&
					!tn.equals("INTEGER UNSIGNED") 
					){
				System.err.println("类型号: " + c.getType() + "	类型名:" + c.getTypename() + "	转换后:" + updateTypeFromDb(c.getType()));
			}

			//			System.out.println(/*p + "\t" + parameterName + "\t" + */);


			ps = ps.replace("PROPERTY_TYPE", generateClassName(p.getType())).
					replace( "COUNT", "" + (i + 1)).replace("PROPERTY_NAME", prop);

			//保证格式的工整
			if(i < cs.size() - 1)
				ps += "\r\t\t\t";
		}

		return ps;
	}

	/**
	 * 根据表列的集合和类名生成PS_SETS字符串，如ps.setInt(1, user.getId());
	 */
	public static String generatePsSets_update(Table table) {
		String parameterName = generateParameterName(table.getName());

		List<Column> cs = getUpdateColumns(table);

		String ps = "";


		Map<String, List<Column>> s = table.getSameColumns();

		Set<String> fund = new HashSet<String>();






		for (int i = 0; i < cs.size(); i++) {
			Property p = generatePropertyFromColumn(cs.get(i));

			String key = cs.get(i).getName().replaceAll("[0-9]", "");
			if(s.containsKey(key)) {

				if(!fund.contains(key)) {
					String temp = "\r\t\t\tfor(int i = 0; i < COL_SIZE; i++) {\r" +
							"\t\t\t\tCOL_SETS\r" +
							"\t\t\t}\r\r";
					temp = temp.replaceAll("COL_SIZE", s.get(key).size() + "");
					temp = temp.replaceAll("COL_SETS", "ps.setPROPERTY_TYPE( i + " + (i + 1) + ", " + parameterName +  ".get" +generateClassName(key) + "(i));");
					temp = temp.replaceAll("PROPERTY_TYPE", generateClassName(p.getType()));
					temp += "\t\t\t";
					ps += temp;
					fund.add(key);
				}
				continue;
			}

			ps += PS;
			String prop = parameterName + ".get"
					+ generateClassName(p.getName()) + "()";
			if ("Date".equals(p.getType())) {
				prop = "new java.sql.Date(" + prop + ".getTime())";
			}
			ps = ps.replace( "PROPERTY_TYPE", generateClassName(p.getType())).
					replace( "COUNT", "" + (i + 1)).
					replace("PROPERTY_NAME", prop);
			//保证格式的工整
			if(i < cs.size() - 1)
				ps += "\r\t\t\t";
		}

		return ps;
	}

	/**
	 * 重新调整
	 * @param table
	 * @return
	 */
	private static List<Column> getUpdateColumns(Table table) {
		List<Column> c = table.getWithOutKeys();
		c.addAll(table.getKeys());
		return c;
	}

	/**
	 * 生成设置分页参数的PsSets
	 * 
	 * @return PAGE_SETS字符串
	 */
	public static String generatePageSets() {
		String ps = "";
		ps += "ps.setInt(1, (pageNo - 1) * pageSize);\r\t\t\t";
		ps += "ps.setInt(2, pageSize);";
		return ps;
	}

	/**
	 * 根据Table对象得到该对象的delete方法的ps.set部分，如ps.setInt(1, id);
	 * 
	 * @param table
	 *            表格对象
	 * @return delete方法的ps.set部分
	 */
	public static String generatePkPsSets(Table table) {
		List<Column> keys = table.getKeys();
		StringBuilder sb = new StringBuilder();
		int i = 0;
		for (Column key : keys) {


			//			System.out.println(key.getName() + "\t" + table.getName() + "\t" + key.getType() );
			sb.append("ps.set" +  generateClassName(updateTypeFromDb(key.getType())) + 
					"(" + ( ++i ) + ", " + key.getName()+ ");\r\t\t\t");
		}
		return sb.toString();
	}

	/**
	 * 根据Table对象得到该表格的主键参数，如：int sno, int cno
	 * 
	 * @param table
	 *            表格对象
	 * @return 主键参数
	 */
	public static String generatePkParameters(Table table) {
		StringBuilder sb = new StringBuilder();

		List<Column> keys =table.getKeys();
		Iterator<Column> it = keys.iterator();
		while (it.hasNext()) {
			Column c = it.next();
			sb.append(updateTypeFromDb(c.getType()) + " " + c.getName() );
			if(it.hasNext()) 
				sb.append(", ");
		}
		return sb.toString();
	}

	/**
	 * 根据Table对象得到该对象的sql语句的主键部分，如：sno = ? AND cno = ?
	 * 
	 * @param table
	 *            表格对象
	 * @return sql语句的主键部分
	 */
	public static String generatePkColumns(Table table) {
		StringBuilder sb = new StringBuilder();

		List<Column> keys =table.getKeys();
		Iterator<Column> it = keys.iterator();
		while (it.hasNext()) {
			Column c = it.next();
			sb.append(c.getName() + " = ?");
			if(it.hasNext())
				sb.append(" AND ");
		}
		return sb.toString();
	}

	/**
	 * 根据Column List获得该对象的update sql语句的where子句部分
	 * 
	 * @return
	 */
	public static String generateColumnParameters(Table table) {

		StringBuilder sb = new StringBuilder();

		List<Column> cs = table.getWithOutKeys();
		Iterator<Column> it = cs.iterator();
		while (it.hasNext()) {
			Column c = it.next();
			sb.append(c.getName() + " = ?");
			if(it.hasNext()) {
				sb.append(", ");
			}
		}
		return sb.toString();
	}

	public static String generateRsGets(Table table) {
		List<Column> columns = table.getColumns();
		String classParameter = generateParameterName(table.getName());
		String rs = "";


		Map<String, List<Column>> s = table.getSameColumns();

		Set<String> fund = new HashSet<String>();


		for (int i = 0; i < columns.size(); i++) {

			Property p = generatePropertyFromColumn(columns.get(i));

			String key = columns.get(i).getName().replaceAll("[0-9]", "");
			if(s.containsKey(key)) {

				if(!fund.contains(key)) {
					String temp = "\r\t\tfor(int i = 0; i < COL_SIZE; i++) {\r" +
							"\t\t\tCOL_SETS\r" +
							"\t\t}\r\r";
					temp = temp.replaceAll("COL_SIZE", s.get(key).size() + "");
					temp = temp.replaceAll("COL_SETS", classParameter + ".set" + generateClassName(key) + "( i, rs.getPROPERTY_TYPE(\"" + key +  "\" + (i + 1)));");
					temp = temp.replaceAll("PROPERTY_TYPE", generateClassName(p.getType()));
					temp += "\t\t";
					rs += temp;
					fund.add(key);
				}
				continue;
			}

			//			for(int i = 0 ; i < 10 ; i++) {
			//				uso.setSkill(i, rs.getInt("skill" + (i + 1)));
			//			}


			Column c = columns.get(i);
			rs += RS;
			rs = rs.replace("CLASS_PARAMETER", classParameter).
					replace("PARAMETER_NAME", firstToUpperCase(hump(c.getName()))).								//成员变量名
					replace("PROPERTY_TYPE", generateClassName(updateTypeFromDb(c.getType()))).	//类型名, String , int long.....
					replace("PROPERTY_NAME", c.getName());

			//						System.out.println(firstToUpperCase(hump(c.getName())));

			//保证格式的工整
			if(i < columns.size() - 1)
				rs += "\r\t\t";
		}



		return rs;
	}

	public static String generateFinders(Table table) {

		String temp =  "public List<CLASS_NAME> findByMETHOD_NAME(COLUMN_TYPE o){\r" +  
				"		PreparedStatement ps = null;\r" + 
				"		ResultSet rs = null;\r" + 
				"		List<CLASS_NAME> ls = new ArrayList<CLASS_NAME>();\r" + 
				"		try {\r" + 
				"			String sql = \"select * from TABLE_NAME where FINDER_COLUMNS\";\r" + 
				"			ps = DbUtils.getPst(sql);\r" + 
				"			FINDER_SETS\r" + 
				"			rs = ps.executeQuery();\r" + 
				"			while (rs.next()) {\r" + 
				"				ls.add(mapping(rs));\r" + 
				"			}\r" + 
				"		} catch (SQLException e) {\r" + 
				"			e.printStackTrace();\r" + 
				"		} finally {\r" + 
				"			DbUtils.free(ps, rs);\r" + 
				"		}\r" + 
				"		return ls;\r" + 
				"	}";

		String[] finders = table.getFindByMethods();

		StringBuilder sb = new StringBuilder();

		for (String fs : finders) {
			Column c = table.getColumns(fs);
			if(fs.isEmpty()) 
				continue;
			sb.append(
					temp.replaceAll("METHOD_NAME", StringUtils.firstToUpperCase(c.getName())).
					replaceAll("COLUMN_TYPE", StringParser.updateTypeFromDb(c.getType())).
					replaceAll("FINDER_COLUMNS", c.getName() + " = ?").
					replaceAll("FINDER_SETS", "ps.set" +  generateClassName(updateTypeFromDb(c.getType())) + 
							"(1, o);\r\t\t\t")
					);
			sb.append("\r\r");
		}
		return sb.toString();

	}
	//	public static void main(String[] args) {
	//		MetaData meta = MetaData.getInstance();
	//		List<Column> labels = meta.getColumnsByTableName("user");
	//		for (int i = 0; i < labels.size(); i++) {
	//			Column label = labels.get(i);
	//			System.out.println(label.getTypename() + ": " + label.getType());
	//		}
	//	}

}
